package com.kk.miaosha.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.kk.miaosha.entity.Menu;
import com.kk.miaosha.entity.RoleMenu;
import com.kk.miaosha.mapper.MenuMapper;
import com.kk.miaosha.service.MenuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kk.miaosha.service.RoleMenuService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * <p>
 * 权限 服务实现类
 * </p>
 *
 * @author kk
 * @since 2020-10-21
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {

    @Resource
    private RoleMenuService roleMenuService;

    //递归查询所有菜单
    @Override
    @Transactional
    public List<Menu> findAllMenu() {
        //1 查询菜单表所有数据
        QueryWrapper<Menu> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("id");
        List<Menu> menuList = baseMapper.selectList(wrapper);
        //2 把查询所有菜单list集合按照要求进行封装
        List<Menu> resultList = bulidMenu(menuList);
        return resultList;
    }
    //=========构建全部菜单=============
    private List<Menu> bulidMenu(List<Menu> menuList) {
        //创建list集合，用于数据最终封装
        List<Menu> finalNode = new ArrayList<>();
        //把所有菜单list集合遍历，得到顶层菜单 pid=0菜单，设置level是1
        for(Menu menuNode : menuList) {
            //得到顶层菜单 pid=0菜单
            if(menuNode.getPid()==0) {
                //设置顶层菜单的level是1
                menuNode.setLevel(1);
                //根据顶层菜单，向里面进行查询子菜单，封装到finalNode里面
                finalNode.add(findChildren(menuNode,menuList));
            }
        }
        return finalNode;
    }

    //DFS
    private Menu findChildren(Menu menuNode, List<Menu> menuList) {
        //1 因为向一层菜单里面放二层菜单，二层里面还要放三层，把对象初始化
        menuNode.setChildren(new ArrayList<Menu>());

        //2 遍历所有菜单list集合，进行判断比较，比较id和pid值是否相同
        for(Menu it : menuList) {
            //判断 id和pid值是否相同
            if(menuNode.getId()==it.getPid()) {
                //把父菜单的level值+1
                int level = menuNode.getLevel()+1;
                it.setLevel(level);
                //如果children为空，进行初始化操作
                if(menuNode.getChildren() == null) {
                    menuNode.setChildren(new ArrayList<Menu>());
                }
                //把查询出来的子菜单放到父菜单里面
                menuNode.getChildren().add(findChildren(it,menuList));
            }
        }
        return menuNode;
    }

    //==========角色构建菜单=============

    //递归删除 DFS
    @Override
    public void removeChildById(int id) {
        //1 创建list集合，用于封装所有删除菜单id值
        List<Integer> idList = new ArrayList<>();
        //2 向idList集合设置删除菜单id
        this.selectMenuChildById(id,idList);
        //把当前id封装到list里面
        idList.add(id);
        baseMapper.deleteBatchIds(idList);
        //级联删除
        roleMenuService.remove(new QueryWrapper<RoleMenu>().in("menu_id",idList));
    }

    //DFS
    private void selectMenuChildById(int id, List<Integer> idList) {
        //查询菜单里面子菜单id
        QueryWrapper<Menu>  wrapper = new QueryWrapper<>();
        wrapper.eq("pid",id);
        wrapper.select("id");
        List<Menu> childIdList = baseMapper.selectList(wrapper);
        //把childIdList里面菜单id值获取出来，封装idList里面，做递归查询
        childIdList.stream().forEach(item -> {
            //封装idList里面
            idList.add(item.getId());
            //递归查询
            this.selectMenuChildById(item.getId(),idList);
        });
    }

    @Override
    @Transactional
    public void saveRoleMenu(int roleId, int[] menuId) {
        //角色原来的权限全删掉
        roleMenuService.remove(new QueryWrapper<RoleMenu>().eq("role_id",roleId));
        //roleId角色id
        //permissionId菜单id 数组形式
        //1 创建list集合，用于封装添加数据
        List<RoleMenu> roleMenuList = new ArrayList<>();
        //遍历所有菜单数组
        for(int mId : menuId) {
            //RolePermission对象
            RoleMenu rolePermission = new RoleMenu();
            rolePermission.setRoleId(roleId);
            rolePermission.setMenuId(mId);
            RoleMenu roleMenu = roleMenuService.getOne(new QueryWrapper<RoleMenu>().eq("role_id", roleId).eq("menu_id", mId));
            if (roleMenu==null){
                //防止出现重复项
                //封装到list集合
                roleMenuList.add(rolePermission);
            }
        }
        //添加到角色菜单关系表
        roleMenuService.saveBatch(roleMenuList);
    }

    @Override
    public HashMap<String, Object> findAllMenuByRole(int roleId) {
        HashMap<String,Object> map=new HashMap<>();
        List<Integer> selectedMenu=new ArrayList<>();
        //获取所有权限
        List<Menu> allMenuList = baseMapper.selectList(new QueryWrapper<Menu>().orderByAsc("id"));

        //根据角色id获取角色权限
        List<RoleMenu> roleMenuList = roleMenuService.list(new QueryWrapper<RoleMenu>().eq("role_id",roleId));
        for (int i = 0; i < allMenuList.size(); i++) {
            Menu menu = allMenuList.get(i);
            for (int m = 0; m < roleMenuList.size(); m++) {
                RoleMenu rolePermission = roleMenuList.get(m);
                if(rolePermission.getMenuId().equals(menu.getId())) {
                    selectedMenu.add(menu.getId());
                    menu.setSelect(true);
                }
            }
        }
        List<Menu> menuList = bulidMenu(allMenuList);
        map.put("children",menuList);
        map.put("selectedMenu",selectedMenu);
        return map;
    }
}
